package com.hmdp.controller;


import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.entity.User;
import com.hmdp.entity.UserInfo;
import com.hmdp.enums.ErrorCodeEnum;
import com.hmdp.service.IUserInfoService;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RedisConstants;
import com.hmdp.utils.RegexUtils;
import com.hmdp.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;

/**
 * 用户信息前端控制器
 *
 * @author leizi
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private IUserService userService;

    @Resource
    private IUserInfoService userInfoService;

    private final StringRedisTemplate redisTemplate;

    public UserController(StringRedisTemplate stringRedisTemplate) {
        this.redisTemplate = stringRedisTemplate;
    }

    /**
     * 发送手机验证码
     */
    @PostMapping("/code")
    public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
        // TODO 校验1分钟内是否已经发送过验证码
        log.info("send sms param code:{}", phone);
        // 校验手机号
        if (!RegexUtils.isPhoneInvalid(phone)) {
            return Result.fail(ErrorCodeEnum.USER_PHONE_FORMAT_FAIL);
        }
        // 发送短信验证码并保存验证码
        String accessCode = userService.sendCode(phone);
        if (!StringUtils.isEmpty(accessCode)) {
            // 验证码存入redis，5分钟过期
            redisTemplate.opsForValue().set(RedisConstants.LOGIN_CODE_KEY + phone, accessCode, RedisConstants.LOGIN_CODE_TTL, TimeUnit.MINUTES);
        }
        return Result.ok();
    }

    /**
     * 登录功能
     *
     * @param loginForm 登录参数，包含手机号、验证码；或者手机号、密码
     */
    @PostMapping("/login")
    public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session) {
        // 获取验证码
        String code = redisTemplate.opsForValue().get(RedisConstants.LOGIN_CODE_KEY + loginForm.getPhone());
        if (StringUtils.isEmpty(loginForm.getCode())) {
            return Result.fail(ErrorCodeEnum.USER_CODE_NOT_EXISTS);
        } else if (!loginForm.getCode().equals(code)) {
            return Result.fail(ErrorCodeEnum.USER_CODE_LOST_EFFECTIVENESS);
        }
        User user = userService.checkUserByPhone(loginForm);
        if (null == user) {
            // 注册用户
            user = userService.registerUser(loginForm);
        }
        // 生成随机令牌
        String token = UUID.randomUUID().toString(true);
        // 保存用户信息, 设置用户登录过期时间30分钟
        redisTemplate.opsForValue().set(RedisConstants.LOGIN_USER_KEY + token, JSON.toJSONString(user.convertDTO()), RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES);

        return Result.ok(token);
    }

    /**
     * 登出功能
     *
     * @return 无
     */
    @PostMapping("/logout")
    public Result logout(HttpServletRequest request) {
        String token = request.getHeader("authorization");
        redisTemplate.delete(RedisConstants.LOGIN_USER_KEY + token);
        return Result.ok();
    }

    @GetMapping("/me")
    public Result me() {
        // 获取当前登录的用户并返回
        return Result.ok(UserHolder.getUser());
    }

    @GetMapping("/info/{id}")
    public Result info(@PathVariable("id") Long userId) {
        // 查询详情
        UserInfo info = userInfoService.getById(userId);
        if (info == null) {
            // 没有详情，应该是第一次查看详情
            return Result.ok();
        }
        info.setCreateTime(null);
        info.setUpdateTime(null);
        // 返回
        return Result.ok(info);
    }

    /**
     * 根据用户id获取博主信息
     *
     * @param userId 用户id
     * @return
     */
    @GetMapping("/{userId}")
    public Result getBloggerInfo(@PathVariable Long userId) {
        return userService.getBloggerInfo(userId);
    }
}
